﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;
using System.Configuration;
using System.Data.SqlClient;
using Model;
using easysql;
namespace Dal
{
    /// <summary>
    /// 数据操作层基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class BaseDal<T> where T : new()
    {
        protected BaseDBHelper dh = null;
        protected string connstr = ConfigurationManager.AppSettings["connstr"];
        protected string databaseType = ConfigurationManager.AppSettings["databaseType"];
        protected static log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        protected string tbname;
        protected BaseDal(string tbname)
        {

            switch (databaseType)
            {
                case "mysql":
                    dh = DBHelperFactory.CreateMysqlHelper(connstr);
                    break;
                case "ms":
                    dh = DBHelperFactory.CreateSqlServerHelper(connstr);
                    break;
            }
            this.tbname = tbname;
        }

        public BaseDBHelper getDh()
        {
            return this.dh;
        }

        public int execute(String sql,params object[] paramValues)
        {
            return dh.Execute(sql, paramValues);
        }

        public List<T> IQueryPage(PageInfo<T> pi,params Restrain[] restrains)
        {
            int total = 0;
            var list = dh.QueryByPage(tbname, pi.query, pi.page, pi.rows, out total, restrains);
            pi.total = total;
            return list;
        }
        public List<T> IQuery(T bean,params Restrain[] restrains)
        {

            return dh.Query(tbname, bean, restrains);
        }
        public void IAdd(T model)
        {
            dh.Add(tbname, model);
        }
        public void IModify(T model)
        {
            dh.Modify(tbname, model);
        }
        public void IDelById(int id)
        {
            dh.DelById(tbname, id);
        }

        /// <summary>
        ///  添加唯一字段的数据
        /// </summary>
        /// <param name="model"></param>
        /// <param name="msg">当添加后数量大约1时的提示信息</param>
        /// <param name="restrains"></param>
        public void IAddOnly(T model, String msg,params Restrain[] restrains)
        {
            BaseDatabase db = dh.CreateDatabaseAndOpen();
            try
            {
                db.BeginTransaction();
                db.Add(tbname, model);
                int count = db.Total<ConfigModel>(tbname, null, restrains);
                if (count > 1)
                {
                    throw new IException(msg);
                }
                db.CommitTranscation();
            }
            catch (Exception ex)
            {
                db.RollbackTranscation();
                throw ex;
            }
            finally
            {
                db.Dispose();
            }
        }



        /// <summary>
        /// 修改唯一字段的数据
        /// </summary>
        /// <param name="model"></param>
        /// <param name="msg"></param>
        /// <param name="restrains"></param>
        public void IModifyOnly(T model,String msg, params Restrain[] restrains)
        {
            BaseDatabase db = dh.CreateDatabaseAndOpen();
            try
            {
                db.BeginTransaction();
                db.Modify(tbname, model);
                int count = db.Total<UserModel>(tbname, null, restrains);
                if (count > 1)
                {
                    throw new IException(msg);
                }
                db.CommitTranscation();
            }
            catch (Exception ex)
            {
                db.RollbackTranscation();
                throw ex;
            }
            finally
            {
                db.Dispose();
            }
        }

        /// <summary>
        /// 批量删除多条记录,如果bean为null,则会删除全部数据
        /// </summary>
        /// <param name="bean"></param>
        public void Del(T bean)
        {
            dh.Del(tbname,bean);
        }

        public T QueryById(int id)
        {
            return dh.QueryById<T>(tbname, id);
        }
        public T QueryOne(T bean,params Restrain[] restrains)
        {
            var list = dh.Query(tbname, bean, restrains);
            if (list.Count > 0)
            {
                return list[0];
            }
            return default(T);
        }


























        [Obsolete("方法已被弃用,请改用新方案", false)]
        protected List<T> PriQuery(T bean, params Restrain[] restrains)
        {
            return dh.Query(tbname, bean, restrains);
        }
        [Obsolete("方法已被弃用,请改用新方案", false)]
        protected List<T> PriQueryByPage(T bean, int page, int rows, out int total, params Restrain[] restrains)
        {
            return dh.QueryByPage(tbname, bean, page, rows, out total, restrains);
        }
        //[Obsolete("方法已被弃用,请改用新方案", false)]
        //protected List<Restrain> trans(QueryPageInfo info)
        //{
        //    List<Restrain> rList = new List<Restrain>();
        //    info.queryEles.ForEach(delegate (QueryEle ele)
        //    {
        //        switch (ele.type)
        //        {
        //            case "like":
        //                rList.Add(Restrain.Like(ele.name, (String)ele.objs[0]));
        //                break;
        //            case "eq":
        //                rList.Add(Restrain.Eq(ele.name, ele.objs[0]));
        //                break;
        //            case "between":
        //                rList.Add(Restrain.Between(ele.name, ele.objs[0], ele.objs[1]));
        //                break;
        //        }
        //    });
        //    return rList;
        //}
        //[Obsolete("方法已被弃用,请改用新方案", false)]
        //protected List<T> PriQueryPage(QueryPageInfo info)
        //{
        //    int total = 0;
        //    var list = dh.QueryByPage<T>(tbname, default(T), info.page, info.rows, out total,trans(info).ToArray());
        //    info.total = total;
        //    return list;
        //}

        [Obsolete("方法已被弃用,请改用新方案", false)]
        protected void PriAdd(T model)
        {
            dh.Add(tbname, model);
        }
        



        [Obsolete("方法已被弃用,请改用新方案", false)]
        /// <summary>
        /// 删除多条记录,如果只提供了id将只删除一条记录
        /// </summary>
        /// <param name="bean"></param>
        /// <returns></returns>
        protected int PriDel(T bean, params Restrain[] restrains)
        {
            return dh.Del(tbname, bean, restrains);
        }
        [Obsolete("方法已被弃用,请改用新方案", false)]
        /// <summary>
        /// 根据id删除一条记录,同事删除关联关系rolemenu
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        protected bool PriDelById(int id)
        {
          
            return dh.DelById(tbname, id);
        }
        [Obsolete("方法已被弃用,请改用新方案", false)]
        /// <summary>
        /// 根据model的id修改记录
        /// </summary>
        /// <param name="model"></param>
        protected void PriModify(T model)
        {
            dh.Modify(tbname, model);
        }
     

        /// <summary>
        /// 查询返回List<dynamic>
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        protected List<dynamic> Query(string sql,params object[] param)
        {
            try
            {
                return ToDynamic(dh.ExecuteDataTable(sql, param));
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        /// <summary>
        /// DateTable转换成List<dynamic> 
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        protected static List<dynamic> ToDynamic(DataTable dt)
        {
            var dynamicDt = new List<dynamic>();
            foreach (DataRow row in dt.Rows)
            {
                dynamic dyn = new System.Dynamic.ExpandoObject();
                var dic = (IDictionary<string, object>)dyn;
                foreach (DataColumn column in dt.Columns)
                {
                    dic[column.ColumnName] = row[column];
                }
                dynamicDt.Add(dyn);
            }
            return dynamicDt;
        }

       // protected void statg


    }
}
